namespace OasisCiq.Xml
{
    using System;
    using System.Collections.Generic;
    using System.Collections.Specialized;
    using System.Linq;
    using System.Xml;

    // TODO: Redesign this class
// ReSharper disable InconsistentNaming
    public class _XmlAttribute
// ReSharper restore InconsistentNaming
    {
        private _XmlAttribute()
        {
        }

        private _XmlAttribute(XmlReader reader)
        {
            if (reader.NodeType != XmlNodeType.Attribute)
            {
                throw new ArgumentException("Invalid reader state! NodeType must be equals to Attribute.");
            }

            NS = reader.NamespaceURI;
            Name = reader.LocalName;
            Value = reader.Value;
        }

        public string NS { get; private set; }

        public string Name { get; private set; }

        public string FullName
        {
            get
            {
                var name = Name;
                if (!string.IsNullOrEmpty(NS))
                {
                    var ns = "{" + NS + "}";
                    name = ns + name;
                }

                return name;
            }
        }

        public string Value { get; private set; }

        public static IEnumerable<_XmlAttribute> GetAttributes(XmlReader reader)
        {
            if (!reader.MoveToFirstAttribute())
            {
                return new _XmlAttribute[0];
            }

            var res = new List<_XmlAttribute>();
            do
            {
                if (reader.LocalName != "xmlns" && reader.Prefix != "xmlns")
                {
                    res.Add(new _XmlAttribute(reader));
                }
            }
            while (reader.MoveToNextAttribute());

            reader.MoveToElement();
            return res;
        }

        public static IEnumerable<_XmlAttribute> GetAttributes(NameValueCollection attributes)
        {
            foreach (var attribute in attributes.AllKeys)
            {
                var ns = string.Empty;
                var localName = attribute;
                if (attribute.StartsWith("{"))
                {
                    var parts = localName.Substring(1).Split('}');
                    ns = parts[0];
                    localName = parts[1];
                }

                yield return new _XmlAttribute
                {
                    NS = ns,
                    Name = localName,
                    Value = attributes[attribute]
                };
            }
        }

        public static NameValueCollection RemoveMissedAttributes(
            NameValueCollection source,
            IEnumerable<_XmlAttribute> remaining)
        {
            var remainingAttrs = (from r in remaining 
                                  select r.FullName).ToArray();
            var sourceAry = source.AllKeys.ToArray();
            foreach (var attr in sourceAry.Where(attr => !remainingAttrs.Any(
                a => string.Equals(a, attr, StringComparison.InvariantCulture))))
            {
                source.Remove(attr);
            }

            return source;
        }

        public static _XmlAttribute GetAttribute(string name, string value)
        {
            var ns = string.Empty;
            var localName = name;
            if (name.StartsWith("{"))
            {
                var parts = localName.Substring(1).Split('}');
                ns = parts[0];
                localName = parts[1];
            }

            return new _XmlAttribute
            {
                NS = ns,
                Name = localName,
                Value = value
            };
        }

        public override string ToString()
        {
            if (string.IsNullOrEmpty(NS))
            {
                return Name + "=" + Value;
            }

            return "{" + NS + "}" + Name + "=" + Value;
        }
    }
}